package com.smsc.headend.task.engine.handler.impl.ansi;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.smsc.headend.common.enums.errorcode.TaskHandlerErrorCode;
import com.smsc.headend.common.utils.RedisKeys;
import com.smsc.headend.common.utils.RedisUtils;
import com.smsc.headend.module.data.dto.DataItemDTO;
import com.smsc.headend.module.protocol.DeviceData;
import com.smsc.headend.module.protocol.ansi.AnsiByteBuffer;
import com.smsc.headend.module.protocol.ansi.AnsiData;
import com.smsc.headend.module.report.entity.LogScheduleTaskDevice;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.module.task.enums.TaskType;
import com.smsc.headend.task.engine.dao.TaskDAO;
import com.smsc.headend.task.engine.exception.UDISTaskHandlerException;
import com.smsc.headend.task.engine.handler.TaskHandler;
import com.smsc.headend.task.engine.handler.impl.collection.strategy.CollectionStrategyFactory;
import com.smsc.headend.task.engine.service.DataProcessService;
import com.smsc.headend.task.engine.service.DeviceStatusService;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import com.smsc.headend.task.engine.service.asset.AssetService;
import com.smsc.headend.task.engine.service.calc.RdEnergyDailyService;
import com.smsc.headend.task.engine.service.task.LogScheduleTaskDeviceService;
import com.smsc.headend.task.engine.service.task.impl.TaskServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;

import java.util.List;
import java.util.Map;

@Slf4j
public class GetLpSettingHandler implements TaskHandler {
    @Autowired
    FeignAssetManagementService assetManagementService;
    @Autowired
    KafkaTemplate kafkaTemplate;
    @Autowired
    DataProcessService dataProcessService;
    @Autowired
    TaskDAO taskDAO;
    @Autowired
    TaskServiceImpl taskService;
    @Autowired
    AssetService assetService;
    @Autowired
    LogScheduleTaskDeviceService logScheduleTaskDeviceService;
    @Autowired
    DeviceStatusService deviceStatusService;
    @Autowired
    RdEnergyDailyService rdEnergyDailyService;
    @Autowired
    RedisUtils redisUtils;

    @Override
    public int handle(Task task, AtomicTask atomicTask, DeviceData deviceData, String actionResult) throws UDISTaskHandlerException {
        if (!(deviceData instanceof AnsiData)) {
            log.error("result={}, data={}", actionResult, deviceData);
            throw new UDISTaskHandlerException(TaskHandlerErrorCode.DEVICE_DATA_TYPE_NOT_SUPPORT.toString());
        }
        AnsiData ansiData = (AnsiData) deviceData;
        log.info("get lp setting {}", ansiData.getAnsiByteBuffer());
        AnsiByteBuffer dataBuffer = ansiData.getAnsiByteBuffer();
        dataBuffer.position(3);
        int NBR_BLKS_SET1 = dataBuffer.getUInt16();
        int NBR_BLK_INTS_SET1 = dataBuffer.getUInt16();
        int NBR_CHNS_SET1 = dataBuffer.getUInt8();
        int MAX_INT_TIME_SET1 = dataBuffer.getUInt8();
        Map<String, Object> param = getParameterMap(task, atomicTask);
        Long lpTemplateId = MapUtil.getLong(param, "lpTemplateId");
        Long lpDataItemId = MapUtil.getLong(param, "dataItemId");
        List<DataItemDTO> dataItemAnsiList = dataProcessService.getLoadProfileCaptureObjects(lpTemplateId, lpDataItemId, task.getMeterId());
        if (dataItemAnsiList.size() != NBR_CHNS_SET1) {
            throw new UDISTaskHandlerException(TaskHandlerErrorCode.UNMATCHED_PROFILE_OBJECTS.toString());
        }
        Integer intervalTime = assetManagementService.getProfileIntervalTime(task.getMeterId(), lpTemplateId);
        if (intervalTime != null) {
            int dbNbrChnsSet1 = intervalTime / 60;
            if (dbNbrChnsSet1 != MAX_INT_TIME_SET1) {
                throw new UDISTaskHandlerException(TaskHandlerErrorCode.PROFILE_PERIOD_MISMATCH.toString());
            }
        }
        Map<String, Object> ansiTaskData = MapUtil.newHashMap();
        ansiTaskData.put("NBR_BLK_INTS_SET1", NBR_BLK_INTS_SET1);
        ansiTaskData.put("NBR_CHNS_SET1", NBR_CHNS_SET1);
        ansiTaskData.put("MAX_INT_TIME_SET1", MAX_INT_TIME_SET1);

        log.info("NBR_BLK_INTS_SET1:{}, NBR_CHNS_SET1:{}, MAX_INT_TIME_SET1:{}", NBR_BLK_INTS_SET1, NBR_CHNS_SET1, MAX_INT_TIME_SET1);
        String ansiTaskDataKey = RedisKeys.getAnsiTaskDataKey(task.getTaskNo());
        redisUtils.hmset(ansiTaskDataKey, ansiTaskData, Long.valueOf(2 * 60 * 60));

        return 1;
    }

    @Override
    public int handleFailure(Task task, AtomicTask atomicTask, String message) {
        log.info("error msg:{}", message);
        if (task.getIsODR()) {
            Map<String, Object> param = getParameterMap(task, atomicTask);
            Long lpDataItemId = Long.valueOf(String.valueOf(param.get("dataItemId")));
            // key 回曲线的dataItemId给web
            taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), Convert.toStr(lpDataItemId), message, 3600l, false);
        }
        if (StrUtil.equalsIgnoreCase(task.getTaskType(), TaskType.ScheduleRead_Profile.name())) {
            logScheduleTaskDeviceService.sendMessage(task, LogScheduleTaskDevice.StatusEnum.Failed.getCode(), LogScheduleTaskDevice.StatusDescEnum.DecodeDataFailed.getCode());
        }
        return -1;
    }

}

